package com.bwie.orders.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.bwie.common.utils.R;
import com.bwie.orders.feign.BargainFeign;
import com.bwie.orders.feign.GoodsFeign;
import com.bwie.orders.vo.*;
import org.apache.commons.lang3.StringUtils;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.Date;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.TimeUnit;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bwie.common.utils.PageUtils;
import com.bwie.common.utils.Query;

import com.bwie.orders.dao.OrderDao;
import com.bwie.orders.entity.OrderEntity;
import com.bwie.orders.service.OrderService;
import org.springframework.transaction.annotation.Transactional;


@Service("orderService")
public class OrderServiceImpl extends ServiceImpl<OrderDao, OrderEntity> implements OrderService {
    @Autowired
    private GoodsFeign goodsFeign;
    @Autowired
    private RabbitTemplate rabbitTemplate;
    @Autowired
    private RedissonClient client;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private BargainFeign bargainFeign;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        QueryWrapper<OrderEntity> wrapper = new QueryWrapper<>();
        String key = (String) params.get("key");
        if (StringUtils.isNotEmpty(key)){
            wrapper.and(w->{
               w.eq("user_id",key);
            });
        }
        IPage<OrderEntity> page = this.page(
                new Query<OrderEntity>().getPage(params),
                wrapper
        );

        return new PageUtils(page);
    }

    @Override
    @Transactional
    public R msAdd(Long userId, Long activityId) {
        //判断秒杀库存是否大于0  大于0说明有库存  解决库存超卖
        RLock myLock = client.getLock("myLock");
        try {
            myLock.lock();
//            ActivityVo activityVo = (ActivityVo) redisTemplate.boundHashOps("activity").get("item" + activityId);
            //查询缓存中活动库存
            R info = goodsFeign.info(activityId);
            ActivityVo activityVo = info.getData(new TypeReference<ActivityVo>() {
            });
            if (activityVo.getStockCount()>0){
              //超买问题：比如一个用户针对一个活动只能买一个，但是发下下了个好几个订单，相当于超买。
              //数据库里面创建联合唯一索引 ，用户id+活动id
                Integer count = (Integer) redisTemplate.opsForValue().get(userId + "And" + activityId + "Count");//redis查一个用户只能买一次
                if (count!=null&&count>0){
                  return R.error("该商品活动已参与");
              }else{
                  //活动表中的秒杀数量-1
                  int count2=activityVo.getStockCount();
                  activityVo.setStockCount(activityVo.getStockCount()-1);
                    R update = goodsFeign.update(activityVo);
                    redisTemplate.boundHashOps("activity").put("item"+activityId,activityVo);//库存放入redis
                  ActivityVo activity = (ActivityVo) redisTemplate.boundHashOps("activity").get("item" + activityId);

                  // 解决订单超卖
                  // 如果库存的update-1 操作正常，就下单成功
                  if (count2>activity.getStockCount()){
                      //mq异步添加订单
                      IdVo idVo = new IdVo();
                      idVo.setActivityId(activityId);
                      idVo.setUserId(userId);
                      redisTemplate.opsForValue().set(userId+"And"+activityId+"Count",1,activityVo.getEndDate().getTime()-new Date().getTime(),TimeUnit.MILLISECONDS);
                      rabbitTemplate.convertAndSend("miaosha","add.orders", idVo);
                      return R.ok().put("userId",userId).put("activityId",activityId);
                  }else {
                      return R.error("库存不足，秒杀失败");
                  }
              }
           }else {
               // 无库存 秒杀失败
               return R.error("库存不足，秒杀失败");
           }
        } finally {

            myLock.unlock();
        }
    }

    @Override
    public OrderEntity getByUidAid(Long userId, Long activityId) {
        return baseMapper.selectByUidAid(userId,activityId);
    }


    //查看回调信息是否有误
    @Override
    public R updateOder(Map<String, String> params) {
        String tradeNo = params.get("out_trade_no");
        OrderEntity orderEntity = baseMapper.selectOne(new QueryWrapper<OrderEntity>().eq("orderno", tradeNo));
        String totalAmount = params.get("total_amount");
        //判断金额
        if (orderEntity.getGoodsPrice().doubleValue()==Double.valueOf(totalAmount)){
            R info2 = goodsFeign.info2(orderEntity.getGoodsId());
            GoodsVo goodsVo = info2.getData(new TypeReference<GoodsVo>() {
            });
            //修改商品表中库存
            goodsVo.setGoodsStock(goodsVo.getGoodsStock()-orderEntity.getGoodsCount());
            goodsFeign.update2(goodsVo);

            orderEntity.setPayDate(new Date());//支付时间
            orderEntity.setStatus(1);//订单状态：0新建未支付，1已支付，2已发货，3已收货，4已退款，5已完成
            baseMapper.updateById(orderEntity);
            return R.ok("支付完成");
        }

        return R.error("金额有误");
    }

    //砍价订单生成
    @Override
    @Transactional
    public R ptAdd(Long userId, Long activityId) {
        //判断拼团活动库存是否大于0  大于0说明有库存  解决库存超卖
        RLock myLock = client.getLock("myLock2");
        try {
            myLock.lock();
            //查询缓存中活动库存
            R info = bargainFeign.info3(activityId);
            BargainVo bargainVo = info.getData(new TypeReference<BargainVo>() {
            });
            if (bargainVo.getStockCount()>0){
                //超买问题：比如一个用户针对一个活动只能买一个，但是发现下了个好几个订单，相当于超买。
                //数据库里面创建联合唯一索引 ，用户id+活动id
                Integer count = (Integer) redisTemplate.opsForValue().get(userId + "And" + activityId + "Count");//redis查一个用户只能买一次
                if (count!=null&&count>0){
                    return R.error("该商品活动已参与");
                }else{
                    //活动表中的秒杀数量-1
                    int count2=bargainVo.getStockCount();
                    bargainVo.setStockCount(bargainVo.getStockCount()-1);
                    R update = bargainFeign.update3(bargainVo);
                    redisTemplate.boundHashOps("activity").put("item"+activityId,bargainVo);//库存放入redis
                    BargainVo bargain = (BargainVo) redisTemplate.boundHashOps("activity").get("item" + activityId);

                    // 解决订单超卖
                    // 如果库存的update-1 操作正常，就下单成功
                    if (count2>bargain.getStockCount()){
                        //mq异步添加订单
                        IdVo idVo = new IdVo();
                        idVo.setActivityId(activityId);
                        idVo.setUserId(userId);
                        redisTemplate.opsForValue().set(userId+"And"+activityId+"Count",1,bargainVo.getEndDate().getTime()-new Date().getTime(),TimeUnit.MILLISECONDS);
                        rabbitTemplate.convertAndSend("miaosha","add.orders2", idVo);
                        return R.ok().put("userId",userId).put("bid",activityId);
                    }else {
                        return R.error("库存不足，秒杀失败");
                    }
                }
            }else {
                // 无库存 秒杀失败
                return R.error("库存不足，秒杀失败");
            }
        } finally {

            myLock.unlock();
        }

    }

//    //砍价
//    @Override
//    public R bargain(Long userId, String id, Long oid) {
//        //添加砍价记录
//        NotesVo notesVo = new NotesVo();
//        R info = goodsFeign.info(oid);//根据订单id查商品信息
//        OrderEntity data = info.getData(new TypeReference<OrderEntity>() {
//        });
//        notesVo.setUserId(userId);
//        notesVo.setGoodsId(data.getGoodsId());
//        notesVo.setBargainId(oid);
//        notesVo.setLastPrice(data.getGoodsPrice());
//        R r = bargainFeign.info3(data.getActivityId());//根据订单表中活动id查砍价活动信息
//        BargainVo data2 = r.getData(new TypeReference<BargainVo>() {
//        });
//        //查询notes记录数据库中  根据userid和barginid
//        int i=bargainFeign.findCount(userId,data.getActivityId());
//        notesVo.setBargainFlag(i+1);//砍价人数+1
//
//        //如果是砍价规则1的话（共 刀砍至低价）
//        if (data2.getRulesflag()==1){
//            // 砍价的次数+1 次数>5就修改订单至最低价
//            if (i+1>5){
//                baseMapper.updatelastPrice(oid,data2.getLastPrice());//修改订单的价钱
//            }
//            bargainFeign.save(notesVo);//添加记录
//        //如果是砍价规则2的话（每刀最多可砍 元）
//        }else if (data2.getRulesflag()==2){
////            //原价-最低价 如果可以砍的钱>0 可以继续砍
////          String subtract = data2.getGoodsPrice().subtract(data2.getLastPrice()).toString();
////            int sub = Integer.parseInt(subtract);
////            if (sub!=0){//不等于0说明还可以继续砍价
////                //修改订单的价钱
////                baseMapper.updatelastPrice(oid,data2.getLastPrice());//修改订单的价钱
////            }else {
////               return R.error("已经砍至最低价");
////            }
//
//        }
//
//        notesVo.setCreateDate(new Date());//砍价记录时间
//        bargainFeign.save(notesVo);//添加记录
//
//        return R.ok("恭喜您帮好友砍了一刀");
//    }

}